package com.example.jeromexiong.testip;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.EthernetManager;
import android.net.IpConfiguration;
import android.net.LinkAddress;
import android.net.NetworkInfo;
import android.net.StaticIpConfiguration;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;

import idea.analyzesystem.android.edittext.AbsEditText;
import idea.analyzesystem.android.edittext.ImeOptionsHelper;
import idea.analyzesystem.android.edittext.ip.IPView;

import static com.example.jeromexiong.testip.NetUtils.getIPv4Address;


public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    StaticIpConfiguration mStaticIpConfiguration;

    IpConfiguration mIpConfiguration;
    EthernetManager mEthManager;

    private String mEthIpAddress = "192.168.1.154";  //IP
    private String mEthNetmask = "255.255.255.0";  //  子网掩码
    private String mEthGateway = "192.168.1.1";   //网关
    private String mEthdns1 = "8.8.8.8";   // DNS1
    private String mEthdns2 = "8.8.4.4";   // DNS2
    TextView textView;
    IPView ipView;
    IPView ipGatewayView;
    IPView ipMaskView;
    IPView ipDNSView;
    IPView ipDNS2View;
    boolean isDHCP = true;
    private boolean isEthernetEnable = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
//        setIP(this, "STATIC");
//        setStaticIP();
        final Context context = this;
        textView = findViewById(R.id.tv_text);

        ipView = findViewById(R.id.ipView);
        ipGatewayView = findViewById(R.id.ip_gateway);
        ipMaskView = findViewById(R.id.ip_mask);
        ipDNSView = findViewById(R.id.ip_dns);
        ipDNS2View = findViewById(R.id.ip_dns2);
        ImeOptionsHelper.onNextAction(getImeOptionWithEditText());

        ipView.setGatewayText(NetUtils.getIpAddress(this).split("\\."));
//        ipView.setGatewayText(mEthIpAddress.split("\\."));
        ipMaskView.setGatewayText(mEthNetmask.split("\\."));
        ipGatewayView.setGatewayText(mEthGateway.split("\\."));
        ipDNSView.setGatewayText(mEthdns1.split("\\."));
        ipDNS2View.setGatewayText(mEthdns2.split("\\."));


        Button cancel = findViewById(R.id.btn_cancel);
        Button confirm = findViewById(R.id.btn_confirm);

        confirm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(context, getEditText(ipView), Toast.LENGTH_LONG).show();
                mEthIpAddress = getEditText(ipView);
                mEthNetmask = getEditText(ipMaskView);
                mEthGateway = getEditText(ipGatewayView);
                mEthdns1 = getEditText(ipDNSView);
                mEthdns2 = getEditText(ipDNS2View);

                setStaticIP();
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        textView.setText(NetUtils.getIpAddress(context));
                    }
                }, 1000 * 5);
            }
        });

        RadioGroup rg_ethernet = findViewById(R.id.rg_ethernet);
        rg_ethernet.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                switch (checkedId) {
                    case R.id.rb_auto:
                        isDHCP = true;
                        Log.d(TAG, "onCheckedChanged: rb_auto");
                        break;
                    case R.id.rb_static:
                        isDHCP = false;
                        Log.d(TAG, "onCheckedChanged: rb_static");
                        break;
                }
            }
        });

        mEthManager = (EthernetManager) getSystemService("ethernet");
        if (mEthManager.getConfiguration().ipAssignment == IpConfiguration.IpAssignment.DHCP) {
            rg_ethernet.check(R.id.rb_auto);
        }else {
            rg_ethernet.check(R.id.rb_static);
        }
        final IpConfiguration ipConfiguration = mEthManager.getConfiguration();
        StaticIpConfiguration configuration = ipConfiguration.getStaticIpConfiguration();
        if (configuration != null) {
            Log.d(TAG, "onCreate: "+mEthManager.getConfiguration().getStaticIpConfiguration().toString());
        }

        Switch s_ethernet = findViewById(R.id.s_ethernet);
        s_ethernet.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked){
                    isEthernetEnable = true;
                    ipConfiguration.setIpAssignment(IpConfiguration.IpAssignment.STATIC);
                }else {
                    isEthernetEnable = false;
                    ipConfiguration.setIpAssignment(IpConfiguration.IpAssignment.UNASSIGNED);
                }
                mEthManager.setConfiguration(ipConfiguration);
                Toast.makeText(MainActivity.this, "以太网是否打开?:" + (isEthernetEnable ? "是" : "否"), Toast.LENGTH_SHORT).show();
            }
        });
    }

    public ArrayList<EditText> getImeOptionWithEditText() {
        ArrayList<EditText> result = new ArrayList<>();
        result.addAll(ipView.getChildEditTextViews());
        result.addAll(ipGatewayView.getChildEditTextViews());
        result.addAll(ipMaskView.getChildEditTextViews());
        result.addAll(ipDNSView.getChildEditTextViews());
        result.addAll(ipDNS2View.getChildEditTextViews());
        return result;
    }

    public String getEditText(IPView ipView) {
        StringBuilder ip = new StringBuilder();
        for (AbsEditText text : ipView.getChildEditTextViews()) {
            ip.append(text.getText().toString()).append(".");
        }
        return ip.substring(0, ip.length() - 1);
    }

    private static InetAddress inetAddress;
    private static Object ipConfigurationInstance;

    /**
     * context 参数，mode参数为静动态模式，分别为 STATIC ,DHCP
     **/
    public static void setIP(Context context, String mode) {
        try {
            // 获取ETHERNET_SERVICE参数
            String ETHERNET_SERVICE = (String) Context.class.getField(
                    "ETHERNET_SERVICE").get(null);
            Class<?> ethernetManagerClass = Class
                    .forName("android.net.EthernetManager");
            Class<?> ipConfigurationClass = Class
                    .forName("android.net.IpConfiguration");
            // 获取ethernetManager服务对象
            Object ethernetManager = context.getSystemService(ETHERNET_SERVICE);
            Object getConfiguration = ethernetManagerClass.getDeclaredMethod(
                    "getConfiguration").invoke(ethernetManager);
            // 获取在EthernetManager中的抽象类mService成员变量
            Field mService = ethernetManagerClass.getDeclaredField("mService");
            // 修改private权限
            mService.setAccessible(true);
            // 获取抽象类的实例化对象
            Object mServiceObject = mService.get(ethernetManager);
            Class<?> iEthernetManagerClass = Class
                    .forName("android.net.IEthernetManager");
            Method[] methods = iEthernetManagerClass.getDeclaredMethods();
            for (Method ms : methods) {
                if (ms.getName().equals("setEthernetEnabled")) {
                    ms.invoke(mServiceObject, true);
                }
            }
            Class<?> staticIpConfig = Class
                    .forName("android.net.StaticIpConfiguration");
            Constructor<?> staticIpConfigConstructor = staticIpConfig
                    .getDeclaredConstructor(staticIpConfig);
            Object staticIpConfigInstance = staticIpConfig.newInstance();
            // 获取LinkAddress里面只有一个String类型的构造方法
            Class<?> linkAddressClass = Class
                    .forName("android.net.LinkAddress");
            Constructor<?> linkAddressConstructor = linkAddressClass
                    .getDeclaredConstructor(String.class);
            // 实例化带String类型的构造方法
            // 192.168.88.22/24--子网掩码长度,24相当于255.255.255.0, 此处必须按照这个样式来设置才行
            Object linkAddress = (Object) linkAddressConstructor
                    .newInstance("192.168.1.22/24");
            Class<?> inetAddressClass = Class.forName("java.net.InetAddress");
            // 默认网关参数
            int[] bytes = new int[]{(byte) 192, (byte) 168, 1, 254};
            Constructor<?>[] inetAddressConstructors = inetAddressClass
                    .getDeclaredConstructors();
            for (Constructor inetc : inetAddressConstructors) {
                // 获取有三种参数类型的构造方法
                if (inetc.getParameterTypes().length == 3) {
                    // 修改权限
                    inetc.setAccessible(true);
                    WifiManager wm = (WifiManager) context
                            .getSystemService("wifi");
                    int ipAddressInt = wm.getConnectionInfo().getIpAddress();
                    // hostName主机名
                    String hostName = String.format(Locale.getDefault(),
                            "%d.%d.%d.%d", (ipAddressInt & 0xff),
                            (ipAddressInt >> 8 & 0xff),
                            (ipAddressInt >> 16 & 0xff),
                            (ipAddressInt >> 24 & 0xff));
                    inetAddress = (InetAddress) inetc.newInstance(2, bytes,
                            hostName);
                }
            }
            // 获取staticIpConfig中所有的成员变量
            Field[] declaredFields = staticIpConfigInstance.getClass()
                    .getDeclaredFields();
            InetAddress address = InetAddress.getByName("192.168.1.1");
            Class<?> threadClazz = Class.forName("android.net.NetworkUtils");
            Method method = threadClazz.getMethod("numericToInetAddress",
                    String.class);
            Object inetAddressObject1 = method.invoke(null, "8.8.8.8");
            Object inetAddressObject2 = method.invoke(null, "8.8.4.4");
            ArrayList<Object> inetAddresses = new ArrayList<Object>();
            inetAddresses.add(inetAddressObject1);
            inetAddresses.add(inetAddressObject2);
            for (Field f : declaredFields) {
                // 设置成员变量的值
                if (f.getName().equals("ipAddress")) {
                    // 设置IP地址和子网掩码
                    f.set(staticIpConfigInstance, linkAddress);
                } else if (f.getName().equals("gateway")) {
                    // 设置默认网关
                    f.set(staticIpConfigInstance, address);
                } else if (f.getName().equals("domains")) {
                    f.set(staticIpConfigInstance, " ");
                } else if (f.getName().equals("dnsServers")) {
                    // 设置DNS，必须要设置才能成功
                    f.setAccessible(true);
                    f.set(staticIpConfigInstance, inetAddresses);
                }
            }
            Object staticInstance = staticIpConfigConstructor
                    .newInstance(staticIpConfigInstance);
            // 存放ipASSignment枚举类参数的集合
            HashMap ipAssignmentMap = new HashMap();
            // 存放proxySettings枚举类参数的集合
            HashMap proxySettingsMap = new HashMap();
            Class<?>[] enumClass = ipConfigurationClass.getDeclaredClasses();
            for (Class enumC : enumClass) {
                // 获取枚举数组
                Object[] enumConstants = enumC.getEnumConstants();
                if (enumC.getSimpleName().equals("ProxySettings")) {
                    for (Object enu : enumConstants) {
                        // 设置代理设置集合 STATIC DHCP UNASSIGNED PAC
                        proxySettingsMap.put(enu.toString(), enu);
                    }
                } else if (enumC.getSimpleName().equals("IpAssignment")) {
                    for (Object enu : enumConstants) {
                        // 设置以太网连接模式设置集合 STATIC DHCP UNASSIGNED
                        ipAssignmentMap.put(enu.toString(), enu);
                    }
                }
            }
            // 获取ipConfiguration类的构造方法
            Constructor<?>[] ipConfigConstructors = ipConfigurationClass
                    .getDeclaredConstructors();
            Class<?> proxyInfo = Class.forName("android.net.ProxyInfo");
            Method methodProxy = proxyInfo.getMethod("buildDirectProxy",
                    String.class, int.class);
            // Object inetAddressObject1 = method.invoke(null, "8.8.8.8");


            for (Constructor constru : ipConfigConstructors) {
                // 获取ipConfiguration类的4个参数的构造方法
                if (constru.getParameterTypes().length == 4) {// 设置以上四种类型
                    // 初始化ipConfiguration对象,设置参数
                    ipConfigurationInstance = constru.newInstance(
                            ipAssignmentMap.get(mode),
                            proxySettingsMap.get("NONE"), staticInstance,
                            methodProxy.invoke(null, null, 0));
                }
            }
            // 获取ipConfiguration类中带有StaticIpConfiguration参数类型的名叫setStaticIpConfiguration的方法
            Method setStaticIpConfiguration = ipConfigurationClass
                    .getDeclaredMethod("setStaticIpConfiguration",
                            staticIpConfig);
            // 修改private方法权限
            setStaticIpConfiguration.setAccessible(true);
            // 在ipConfiguration对象中使用setStaticIpConfiguration方法,并传入参数
            setStaticIpConfiguration.invoke(ipConfigurationInstance,
                    staticInstance);
            Object ethernetManagerInstance = ethernetManagerClass
                    .getDeclaredConstructor(Context.class,
                            iEthernetManagerClass).newInstance(context,
                            mServiceObject);
            ethernetManagerClass.getDeclaredMethod("setConfiguration",
                    ipConfigurationClass).invoke(ethernetManagerInstance,
                    ipConfigurationInstance);
        } catch (InvocationTargetException e) {
            System.out.println("此处接收被调用方法内部未被捕获的异常");
            Throwable t = e.getTargetException();// 获取目标异常
            t.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void setStaticIP() {
        mEthManager = (EthernetManager) getSystemService("ethernet");
        mStaticIpConfiguration = new StaticIpConfiguration();
        Inet4Address inetAddr = getIPv4Address(mEthIpAddress);
        int prefixLength = NetUtils.maskStr2InetMask(mEthNetmask);
        InetAddress gatewayAddr = getIPv4Address(mEthGateway);
        InetAddress dnsAddr = getIPv4Address(mEthdns1);

        if (inetAddr.getAddress().toString().isEmpty() || prefixLength == 0 || gatewayAddr.toString().isEmpty()
                || dnsAddr.toString().isEmpty()) {
            return;
        }

        Class<?> clazz = null;
        try {
            clazz = Class.forName("android.net.LinkAddress");
        } catch (Exception e) {
            // TODO: handle exception
        }

        Class[] cl = new Class[]{InetAddress.class, int.class};
        Constructor cons = null;

        //取得所有构造函数
        try {
            cons = clazz.getConstructor(cl);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        //给传入参数赋初值
        Object[] x = {inetAddr, prefixLength};

        String dnsStr2 = mEthdns2;
        //mStaticIpConfiguration.ipAddress = new LinkAddress(inetAddr, prefixLength);
        try {
            mStaticIpConfiguration.ipAddress = (LinkAddress) cons.newInstance(x);
            Log.d("232323", "chanson 1111111");
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        mStaticIpConfiguration.gateway = gatewayAddr;
        mStaticIpConfiguration.dnsServers.add(dnsAddr);

        if (!dnsStr2.isEmpty()) {
            mStaticIpConfiguration.dnsServers.add(getIPv4Address(dnsStr2));
        }

        Log.d("2312321", "chanson mStaticIpConfiguration  ====" + mStaticIpConfiguration);

        mIpConfiguration = new IpConfiguration(isDHCP ? IpConfiguration.IpAssignment.DHCP : IpConfiguration.IpAssignment.STATIC, IpConfiguration.ProxySettings.NONE, mStaticIpConfiguration, null);
//        mEthManager.set
        mEthManager.setConfiguration(mIpConfiguration);
    }
    private void getAndSetEthernetManagerByReflection() {
        // 通过反射调用
        try {
            // 获取ETHERNET_SERVICE参数
            String ETHERNET_SERVICE = (String) Context.class.getField("ETHERNET_SERVICE").get(null);
            //
            Class<?> ethernetManagerClass = Class.forName("android.net.ethernet.EthernetManager");
            // 获取ethernetManager服务对象
            Object ethernetManager = getSystemService(ETHERNET_SERVICE);
            ethernetManagerClass.getDeclaredMethod("setEthernetEnabled", boolean.class).invoke(ethernetManager,
                    isEthernetEnable);
        } catch (IllegalAccessException | NoSuchFieldException | NoSuchMethodException | ClassNotFoundException
                | InvocationTargetException e) {
            e.printStackTrace();

        }
    }
}